查看原文
其他

你要选择哪条路?

刘欣 码农翻身 2018-10-25

在我们这个世界中, 操作系统老大绝对是最神秘的,我们这些进程想和他通信,只能通过那所谓的系统调用,例如open,close, socket,connect 等等。


我对自己的一亩三分地非常熟悉,这是一个地址空间,虽说是虚拟的,但是我却并不在意。


这个地址空间被划分成若干区域:



我的工作就是配合CPU阿甘去执行代码区的那些代码,代码有时候非常简单,就是把一些数字加加减减; 有时候则是复杂的函数调用,这时候“栈”就得出马,把各种调用参数入栈,出栈; 有时候会动态分配一点内存,此时我的“堆”就要大显身手了。


让我感到奇怪的是,这些代码运行起来似乎无穷无尽,很久之后我才悟出来,其实我一直在一个循环中打转,人类故意让我走不出来。


这一次我遇到了一段代码:


pid_t pid;
int count = 10;
pid = fork();
if( pid >0 ){
 count++;
 printf("Parent process\n");  
 ...其他处理...
} else if (pid==0){
  count--;
  printf("Child process\n");
  ...其他处理...
} else{
   err_exit("error occured ");
}


当我准备按照之前的方式执行的时候,我遇到了系统调用Fork先生。


这位Fork先生根本就没有理我, 在那里不停地吟唱一首诗:


一片树林里分出两条路,

而我选择了人迹更少的一条,

从此决定了我一生的道路。


我不知道他为什么如此钟情于这首诗,只得提醒道:“嗨,哥们儿,要系统调用了啊。”


他瞥了我一眼:“你要选哪条路?”


哪条路?


我看了看自己的代码,确实有三个分支, 但是走哪个分支依赖于Fork先生返回给我的结果pid啊,我没得选择。


我把自己的想法告诉他。


Fork先生开始和操作系统老大通话,过了一会儿, 告诉我:“走第一个分支。”


然后他又开始吟唱那首诗了: 一片树林里分出两条路......


过了一会儿,我又要执行这段代码了,Fork先生还是问道:“你要选哪条路?”


我估计这厮太无聊,故意没事找事,就没搭理他。


他照例和操作系统老大通话后,告诉我:“走第一个分支。”


第3次,第4次,第5次...... 每次我执行这段代码,爱吟唱的Fork先生总是说:“走第一个分支。”


每次都是走第一个分支!


这不由得引起了我的怀疑: Fork先生是不是搞错了? 我怎么永远都走不到第二个分支去呢?  那第二个分支的代码有什么用处? 人类不会这么愚蠢地写无用的代码吧?


我偷偷问CPU阿甘:“兄弟, 我的第二个分支你执行过吗?”


CPU阿甘飞快地说:“当执行过!执行过好几次呢!”


这就见鬼了,Fork先生从来没让我走过第二个分支啊。


阿甘解释说:“不是在你这里执行的,是通过你fork出来的进程执行的。”


“我fork出的进程?”


“对啊, 那个Fork先生的工作不就是创建新进程的吗?”  阿甘反问。


“创建的新进程和我有什么关系?”


“当然属于你的子进程啊, 这个子进程也有自己的一亩三分地, 但是复制了你的栈,堆和数据区,不过他和你共享了代码段。”




“共享了老子的代码段? 我怎么不知道?”


“你当然不知道了喽,不过这对你也没有影响啊,那个fork调用如果创建子进程成功,给你返回的就是子进程的进程号了,给子进程返回的值就是0。


“你就胡扯吧, 一个fork调用能返回两次? ” 我绝不相信, 这完全颠覆了我的世界观。


“信不信由你, 反正子进程创建以后,由于和你是共享了代码段,也会从pid=fork()这一行代码处开始执行,只不过子进程得到的pid是0,所以就走了第二个分支!”



我现在有点理解爱吟唱的诗人Fork先生了,他的的确确是返回了两次,每个进程一次。


怪不得他整天吟唱“ 一片树林里分出两条路......” 这可不就是两条路啊,只不过我们没得选择。


我甚至能想象得出他像问我一样故意问子进程要走那条路,子进程每次都得走第二个分支。


我还注意到我的那个局部变量count = 10 ,也被复制到了子进程的栈中,很明显,子进程会把它减去1,变为9。 我这里则会加上1, 变成11, 我们两个互不影响。


我好奇地问阿甘:“我的子进程共享我的代码段,我们都执行一模一样的代码,似乎没什么意义啊!”


阿甘说:“我阅代码无数,能从无数指令中总结出你们进程的目的, 我估计你啊就是一个Web服务器程序,你就是等待客户端的请求,请求来了以后你用fork创建子进程去处理(进入了代码的另外一个分支),然后你继续等待。”


我觉得阿甘说得很有道理,可还是追问道:“要是新fork的进程确实需要执行新的程序呢?”


阿甘说道:“那就是另外一个系统调用exec了, 这位先生可以把装载新的程序,替换掉进程的代码段中的代码,重置栈,堆和数据段,一切从头开始。


在对操作系统老大增加了几分敬畏之情的同时, 我暗自感慨,没想到创建一个新的进程,背后要发生这么多的事情啊。


(完)

你看到的只是冰山一角, 更多精彩文章,请移步《2016文章精华》或者《2017文章精华


码农翻身

用故事讲述技术

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存